﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Slaks.DocumentSerialization.Document;
using Slaks.DocumentSerialization.TermIdInfo;
using DataInput;
using System.Reflection;
using Slaks.Graphs.Algorithms;

namespace Slaks.Graphs.GraphBuilder
{
    public interface IGraphProperty
    {
        string Name { get; }
        object Value { get; }
        
    }
    public class GraphProperty:IGraphProperty
    {
        public string Name { get; private set; }

        public object Value { get; private set; }

        public GraphProperty(string name, object value)
        {
            Name = name;
            Value = value;
        }

        public override bool Equals(object obj)
        {
            GraphProperty other = obj as GraphProperty;
            if (other != null)
                return other.Name.Equals(this.Name);
            return false;
        }
        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }
    }

    public class GraphBuilderBase : IRepresentation
    {
        private const String VerticiesParam = "Verticies to leave";
        public const String BuilderTypeParam = "BuilderType";
        protected const String nParameterParam = "nParameter";
        int nParameter;
        int numberOfVerticesToLeave;
        public IEnumerable<IGraphProperty> GraphProperties
        {
            get
            {
                return _properties.ToArray();
            }
        }

        protected GraphBuilderBase()
        {
            
        }
        
        protected void AddProperty(IGraphProperty property)
        {
            _properties.Remove(property);
            _properties.Add(property);
        }
        protected virtual void AddGraphBuilderProperties()
        {
        }
        private readonly IList<IGraphProperty> _properties = new List<IGraphProperty>();

        public string Description
        {
            get
            {
                return GetBuilderDescription();
            }
        }
        public string Name
        {
            get
            {
                return GetBuilderName();
            }
        }

        protected virtual string GetBuilderName()
        {
            return GetType().Name;
        }

        protected virtual string GetBuilderDescription()
        {
            return GetType().Name;
        }


        #region IRepresentation Members

        public virtual BuilderType getBuilderType()
        {
            return (BuilderType) Enum.Parse(typeof(BuilderType),GetType().Name,false);
        }

        private class BuilderTypeProperties
        {
            private BuilderType currentBuilderType;
            public BuilderType builderType
            {
                get
                {
                    return currentBuilderType;
                }
                set
                {
                    currentBuilderType = value;
                }
            }
        }

        public static Dictionary<string, object> getAllBuilderTypes()
        {
            Dictionary<string, object> builderTypes = new Dictionary<string, object>();
            BuilderTypeProperties profile = new BuilderTypeProperties(); 
            foreach (PropertyInfo propertyInfo in profile.GetType().GetProperties())
            {
                if ((propertyInfo.PropertyType.IsEnum) && (propertyInfo.PropertyType.IsPublic))
                {
                    String [] names = Enum.GetNames ( propertyInfo.PropertyType );                    
                    for ( int i = 0; i < names.Length; i++ )
                    {
                        BuilderType value = ( BuilderType ) Enum.ToObject ( propertyInfo.PropertyType, i);
                        builderTypes.Add ( names [ i ], value );
                    }                    
                }
            }
            
            
            return builderTypes;
        }

        public List<Field> fields;

        // TODO remove unnecessay paramter into fields.

        public Graph Build(Document document,TermIdInfoMap map, IEnumerable<Field> fields)
        {
            SetDynamicValues(fields);
            return Build(document,this.numberOfVerticesToLeave,this.nParameter,map);
        }

        public virtual List<Field> GetDynamicFields()
        {
            List<Field> fields = new List<Field>();
            fields.Add(new TextField(VerticiesParam, "Graph size:", "5", false, true ));
            fields.Add(new TextField(nParameterParam, "n parameter:", "0", false, true ));
            return fields;
        }
       
        public virtual void SetDynamicValues(IEnumerable<Field> fields)
        {
            foreach (var field in fields)
            {
                if (field.FieldName == VerticiesParam)
                    numberOfVerticesToLeave = int.Parse(field.Value.ToString());
                if (field.FieldName == nParameterParam )
                    nParameter = int.Parse(field.Value.ToString());                
            }
        }

        public Graph Build(Document document, int numberOfVerticesToLeave)
        {
            return Build(document,numberOfVerticesToLeave,0,null);
        }
        public Graph Build(Document document, int numberOfVerticesToLeave, TermIdInfoMap map)
        {
            return Build(document,numberOfVerticesToLeave,0,map);
        }
        public Graph Build(Document document, int numberOfVerticesToLeave, int nParameter)
        {
            return Build(document,numberOfVerticesToLeave,nParameter,null);
        }
		virtual protected Graph Build(Document document, int numberOfVerticesToLeave,int nParameter, TermIdInfoMap map)
		{
			Graph graph =  new Graph();
			graph.GraphBuilderType = getBuilderType();
			return graph;
		}

        #endregion
    }
}
